home *** CD-ROM | disk | FTP | other *** search
/ Plug-In Power Pack for Netscape Communicator / Plug-In Power Pack for Netscape Communicator.iso / plugins / dataviews / dvtools / examples / fds / fdseval / fdseval.c next >
C/C++ Source or Header  |  1997-07-10  |  56KB  |  1,918 lines

  1. #ifndef lint
  2.   static char SccsId[]="@(#)FDSeval.c    V1.46    6/14/95";
  3. #endif
  4. /*
  5. |    file name - FDSeval.c
  6. |===================================================================
  7. |
  8. |              copyright (c) 1989, V.I. Corporation
  9. |
  10. |    FDSeval.c - Yacc file for expression parser, FDSeval
  11. |
  12. |    Alan C Morse    31 may 89
  13. |
  14. |===================================================================
  15. |
  16. |    Procedure description/function:
  17. |    Contains yacc description for FDSeval, the example
  18. |    expression evaluator function data source for DV-Draw
  19. |    and DV-Tools.
  20. |
  21. |    This parses c-like expression strings, which may get
  22. |    arguments from the environment.  These arguments
  23. |    are denoted in the expression by $n, where n is in
  24. |    the range [1-9].  The program works by building a parse
  25. |    tree the first time it encounters an expression and
  26. |    evaluating the tree every time the select function
  27. |    is called for the variable.  Nodes in the parse tree
  28. |    can reference data source variables, which are read
  29. |    each time the expression is evaluated.
  30. |
  31. |    Expressions may contain symbols (name strings), which
  32. |    define data that is local to the data source. When
  33. |    the expressions are parse, the symbols are converted
  34. |    to ids and a data area is built for the data source.
  35. |    This data area is a linked list of id-value pairs
  36. |    (where the ids are INTs and the values are DOUBLEs.)
  37. |    As each expression is parsed, the symbol in the expression
  38. |    gets translated to an address of the corresponding
  39. |    value in the data area.
  40. |    
  41. |    The data structures are as follows:
  42. |    
  43. |    STATIC DATA GLOBAL TO THIS MODULE
  44. |    
  45. |    1. SymbolNameTable is a symbol table mapping variable names
  46. |    to unique numeric ids.  Parsing translates all string names
  47. |    to unique integers to simplify the structure of the parse
  48. |    tree.  For example, this means that all variables named "i"
  49. |    get replaced with the same id (token) in all expressions.
  50. |    
  51. |    2. GlobalEnv contains information about the current expression
  52. |    being evaluated. It includes information about the current
  53. |    data source or data source variable. It is a (admittedly ugly)
  54. |    way of passing contextual information around in case any of
  55. |    the evaluation routines need information about who invoked them.
  56. |    
  57. |    DATA GLOBAL WITHIN A DATASOURCE
  58. |    
  59. |    1. DataArea where the values associated with variable names are
  60. |    stored. Since the scope of a variable name in an expression is
  61. |    the data source that contains it, DataArea must be maintained by
  62. |    the data source, not the data source variable. DataArea is
  63. |    implemented as a list of id-datum pairs.
  64. |    
  65. |    DATA TYPES
  66. |    
  67. |    1. An expression is a linked list of root parse tree nodes,
  68. |    where each root node corresponds to a statement. A parse
  69. |    tree node has a value (recalculated every time the tree is
  70. |    evaluated, but which may be a constant), a function, and a
  71. |    list of parse subtrees.
  72. |
  73. |===================================================================
  74. */
  75. # include "std.h"
  76. # include "dvstd.h"
  77. # include "FDSeval.h"
  78. # include "dvfds.h"
  79. # include "dvtools.h"
  80. # include "dvtoolfuns.h"
  81. # include "ringbuf.h"
  82. # include "VTmiscfuns.h"
  83. # include "FDSmiscfuns.h"
  84. # include "VIiofuns.h"
  85. # include "MISCfuns.h"
  86. # include "VIstrfuns.h"
  87. # include "Tfundecl.h"
  88.  
  89.  
  90. #ifdef RS6000
  91. #ifndef __MATH__
  92. #define __MATH__
  93. #endif
  94. #endif
  95.  
  96. # include <math.h>
  97.  
  98.  
  99. #ifdef RS6000
  100. #ifdef __MATH__
  101. #undef __MATH__
  102. #endif
  103. #endif
  104.  
  105. LOCAL DOUBLE StringToDouble(); 
  106. #ifndef ALPHA
  107. long random();
  108. #endif
  109. LOCAL DOUBLE assign(), assign_to_dsv(),
  110.        mult(), divide(), add(), minus(), neg(), mod(),
  111.        EQtest(), NEtest(), LTtest(), LEtest(), GTtest(), GEtest(),
  112.        readsym(), readvar(), cond();
  113.  
  114. LOCAL VOID GetFcn();
  115. LOCAL FCN fcn;
  116. LOCAL INT numargs;
  117.  
  118. /*----------------------------------------------------------------*/
  119. /*                  SYMBOL ID MANAGEMENT ROUTINES                 */
  120. /*----------------------------------------------------------------*/
  121. typedef INT SYMBOL_ID;
  122.   
  123. /* The table is a list of symbol ids with corresponding pointers to  */
  124. /* data locations, where the DOUBLE value associated with the   */
  125. /* name is stored. */
  126.  
  127. /* There is a global table of symbol-string to symbol-id mappings */
  128. /* This associates a unique 4-byte number with each name, allowing more */
  129. /* compact storage */
  130.  
  131. /* Convert a symbol string to a symbol id, by looking up the symbol
  132.    in a global table of symbol-name-to-id mappings.
  133. */
  134. LOCAL ADDRESS SymbolNameTable = 0;
  135. LOCAL SYMBOL_ID SymbolIdCounter = 0;
  136.  
  137. LOCAL SYMBOL_ID ConvertNameToSymbol( symbol_name )
  138.   CHAR *symbol_name;
  139. {
  140.   ADDRESS hashnode;
  141.   
  142.   /* Make sure the table has been created */
  143.   if( (ADDRESS)0 == SymbolNameTable )
  144.     SymbolNameTable = VThtcreate( (CHAR*)0, VThtstrconvert,
  145.                  (VTHTCOMPAREFUNPTR)strcmp );
  146.  
  147.   /* If the symbol is not in the table, add it and give it a unique id */
  148.   /* In any case, return its unique id. */
  149.   hashnode = VThtkeyfind( SymbolNameTable, symbol_name );
  150.   if( hashnode )
  151.     return (SYMBOL_ID)VThnvalue( hashnode );
  152.   else
  153.     {
  154.     ++SymbolIdCounter; /* Generate a new uniqe symbol id */
  155.     VThthninsert( SymbolNameTable,
  156.          VIstrclone( symbol_name ), (int*)SymbolIdCounter );
  157.     return SymbolIdCounter;
  158.     }
  159.   }
  160.  
  161. LOCAL CHAR *ConvertSymbolToName( symbol_id )
  162.   SYMBOL_ID symbol_id;
  163. {
  164.   ADDRESS hashnode;
  165.   
  166.   /* Make sure the table has been created */
  167.   if( (ADDRESS)0 == SymbolNameTable )
  168.     return (CHAR*)0; /* Symbol id has no name */
  169.   /* If the symbol ID is in the table, */ 
  170.   /* return the string associated with it; */
  171.   /* Otherwise, return 0 */
  172.   hashnode = VThtvalfind( SymbolNameTable, (ADDRESS)0, (INT*)symbol_id );
  173.   if( hashnode )
  174.     return (CHAR*)VThnkey( hashnode );
  175.   else
  176.     return (CHAR*)0;
  177.   }
  178.  
  179.  
  180. /*----------------------------------------------------------------*/
  181. /*                  DATA AREA MANAGEMENT ROUTINES                 */
  182. /*----------------------------------------------------------------*/
  183. /* DataArea types: this is "memory" where data associated with    */
  184. /* symbols is stored. */
  185. typedef struct DataAreaEntry
  186.   {
  187.   struct DataAreaEntry *next;
  188.   SYMBOL_ID SymbolId;
  189.   DOUBLE DataValue;
  190.   } DATA_AREA_ENTRY;
  191.   
  192. typedef struct
  193.   {
  194.   DATA_AREA_ENTRY *FirstDataEntry;
  195.   } DATA_AREA;
  196.   
  197. /* Create a data area */
  198. LOCAL DATA_AREA *daCreate()
  199.   {
  200.   DATA_AREA *NewDataArea;
  201.  
  202.   NewDataArea = (DATA_AREA*)S_ALLOC( sizeof(DATA_AREA) );
  203.   NewDataArea->FirstDataEntry = (DATA_AREA_ENTRY*)0;
  204.   return NewDataArea;
  205.   }
  206.  
  207. /* Destroy a data area */
  208. LOCAL VOID daDestroy( DataArea )
  209.   DATA_AREA *DataArea;
  210.   {
  211.   DATA_AREA_ENTRY *entry, *next_entry;
  212.   
  213.   for( entry = DataArea->FirstDataEntry, next_entry = (DATA_AREA_ENTRY*)0;
  214.        entry;
  215.        entry = next_entry )
  216.     {
  217.     next_entry = entry->next;
  218.     S_FREE( (char*)entry );
  219.     }
  220.   S_FREE( (char*)DataArea );
  221.   }
  222.   
  223. /* Adds an entry to the data area */
  224. LOCAL VOID daAddEntry( DataArea, SymbolId  )
  225.   DATA_AREA *DataArea;
  226.   SYMBOL_ID SymbolId;
  227.   {
  228.   DATA_AREA_ENTRY *new_entry, *entry;
  229.  
  230.   for( entry = DataArea->FirstDataEntry; entry; entry = entry->next )
  231.     {
  232.     if( entry->SymbolId == SymbolId )
  233.       return; /* Symbol is already in the list */
  234.     }
  235.  
  236.   /* If we get here, entry is not in the list. */
  237.   new_entry = (DATA_AREA_ENTRY*)S_ALLOC( sizeof(DATA_AREA_ENTRY) );
  238.  
  239.   /* Add entry to the beginning of the list */
  240.   new_entry->next = DataArea->FirstDataEntry;
  241.   new_entry->SymbolId = SymbolId;
  242.   new_entry->DataValue = 0.0;
  243.   DataArea->FirstDataEntry = new_entry;
  244.   }
  245.  
  246. /* Gets address of datum associated with a given symbol id */
  247. LOCAL DOUBLE DummyValue = 0;
  248. LOCAL DOUBLE* daGetDatumAddress( DataArea, SymbolId )
  249.   DATA_AREA *DataArea;
  250.   SYMBOL_ID SymbolId;
  251.   {
  252.   DATA_AREA_ENTRY *entry;
  253.  
  254.   for( entry = DataArea->FirstDataEntry; entry; entry = entry->next )
  255.     {
  256.     if( entry->SymbolId == SymbolId )
  257.       return &entry->DataValue;
  258.     }
  259.   return (DOUBLE*)&DummyValue;
  260.   }
  261.   
  262. /* ---------------------------------------------------------------*/
  263. /*         PARSE TREE NODE TYPE DEFINITION                        */
  264. /* ---------------------------------------------------------------*/
  265. /* Each expression generates a linked list of parse trees, which  */
  266. /* are evaluated sequentially. */
  267. #define MAX_SUBTREES 3
  268. typedef struct ParseTreeNode
  269.   {
  270.   DOUBLE value;
  271.   FCN fcn;
  272.   ADDRESS params;/* Parameter area for use by function, fcn.  Memory
  273.     | is allocated by fcn, but freed by PTNdestroy.  This data area
  274.     | allows the function to maintain state information from one
  275.     | call to the next.  */
  276.   VOID (*FreeParams)(); /* Function for freeing the parameter area */
  277.   struct ParseTreeNode *Subtree[MAX_SUBTREES];
  278.   } NODE;
  279.  
  280. typedef struct expstruct
  281.   {
  282.   struct expstruct *next;
  283.   NODE *exp;
  284.   } EXPRESSION;
  285.  
  286. LOCAL NODE *PTNcreate();
  287. LOCAL VOID PTNdestroy();
  288. LOCAL DOUBLE PTNeval();
  289.  
  290. #ifdef DEBUG
  291. LOCAL VOID PTNprint();
  292. #endif
  293.  
  294. /*---------------------------------------------------------------*/
  295. /*      Parameter area for the eval function data source       */
  296. /*---------------------------------------------------------------*/
  297. typedef struct
  298.   {
  299.   EXPRESSION *read_explist;/* Exp list to be evaluated by read every time. */
  300.   DATA_AREA *data_area; /* Where data associated with symbols is kept */
  301.   } EVAL_PARAMS;
  302.  
  303. LOCAL EVAL_PARAMS *CurrentParams;
  304.  
  305. /* ---------------------------------------------------------------*/
  306.  
  307. #ifdef YYDEBUG
  308. LOCAL DV_BOOL debug = YES;
  309. #else
  310. LOCAL DV_BOOL debug = NO;
  311. #endif
  312. LOCAL DOUBLE number;
  313. LOCAL NODE *ParseResult = 0;
  314. LOCAL CHAR id[30];
  315. LOCAL INT CurrentArgIndex;
  316.  
  317. /* Global variable giving contextual information of the expression */
  318. /* that is being evaluated */
  319. LOCAL struct
  320.   {
  321.   NODE* CurrentNode; /* Current node in parse tree */
  322.   V_FDS_FCN_ENUM FdsFunType; /* Type of fds function */ 
  323.                  /* that invoked evaluation */
  324.   CHAR *CurrentFunction; /* Name of type of invoking fds function */
  325.   } GlobalEnv;
  326.  
  327.  
  328. typedef union 
  329.   {
  330.   NODE *Nval;
  331.   double dval;
  332.   int ival;
  333.   SYMBOL_ID Sval;
  334.   FCN Fval;
  335.   ADDRESS Aval; 
  336.   } YYSTYPE;
  337. # define EXPR_ARG_MARKER 257
  338. # define ID 258
  339. # define EVAL_NUMBER 259
  340. # define TERMINATOR 260
  341. # define INCLUDE_FILE 261
  342. # define EQ 262
  343. # define NE 263
  344. # define LE 264
  345. # define GE 265
  346. # define LT 266
  347. # define GT 267
  348. # define NEG 268
  349. #define yyclearin yychar = -1
  350. #define yyerrok yyerrflag = 0
  351. extern int yychar;
  352. extern int yyerrflag;
  353. #ifndef YYMAXDEPTH
  354. #define YYMAXDEPTH 150
  355. #endif
  356. YYSTYPE yylval, yyval;
  357. # define YYERRCODE 256
  358.  
  359.  
  360. #include "FDSevallex.h"
  361.  
  362. /* -------------------------------------------------------------*/
  363. /*        Conversion routines                */
  364. /* -------------------------------------------------------------*/
  365. LOCAL DOUBLE StringToDouble( s )
  366.   CHAR *s;
  367. {
  368.   DOUBLE number = 0;
  369.  
  370.   if( 1 != S_SSCANF( s, "%lf", &number ) )
  371.     number = 0;
  372.   return number;
  373.   }
  374.   
  375. /* -------------------------------------------------------------*/
  376. /*        Error Handling and echoing functions        */
  377. /* -------------------------------------------------------------*/
  378. /* Local routine to print an error string, specifying the */
  379. /* datasource and dsvar in which it occurred. */
  380. LOCAL void PrintErrString( errstring )
  381.   CHAR *errstring;
  382.   {
  383.   /* What and where of error message */
  384.   (VOID)S_FPRINTF( stderr,"FDSeval: %s (DS: %s",
  385.           errstring, TdsGetName(M_dscurrent) );
  386.   if( M_dsvcurrent )
  387.     /* Error is in select function of dsvar */
  388.     (VOID)S_FPRINTF( stderr,", DSV: %s)\n", TdsvGetName(M_dsvcurrent) );
  389.   else
  390.     /* Error is in open or read for ds */
  391.     (VOID)S_FPRINTF( stderr,": %s)\n", GlobalEnv.CurrentFunction );
  392.   }
  393.  
  394. LOCAL void yyerror( errstring )
  395.   CHAR *errstring;
  396.   {
  397.   CHAR c;
  398.   CHAR *substart, *subend; /* Subexpression start and end */
  399.   INT err_offset; /* Number of characters from beginning or expression
  400.              where error occurs. */
  401.  
  402.   PrintErrString( errstring );
  403.  
  404.   /* Find the portion of the string that contains the error */
  405.   /* by locating the beginning and ending of the current expression. */
  406.   substart = subend = expression;
  407.   err_offset = 0;
  408.   while( substart != ExpStart && *substart != '\n' )
  409.     { substart--; err_offset++; } 
  410.   if( *substart == '\n' ) substart++;
  411.   
  412.   while( *subend != '\0' && *subend != '\n' && *subend != ';' )
  413.     subend++;
  414.  
  415.   /* Echo the expression */
  416.   c = *subend;
  417.   *subend = '\0';
  418.   (VOID)S_FPRINTF( stderr,"  %s\n", substart );
  419.   *subend = c;
  420.  
  421.   /* Place marker indicating approximate position of error */
  422.   for( ; err_offset > 0; err_offset-- )
  423.     (VOID)S_FPRINTF( stderr, " " );
  424.   (VOID)S_FPRINTF( stderr, "^^^\n" );
  425.   }
  426.   
  427. LOCAL VOID ErrFcnUndefined( FcnNameId )
  428.   SYMBOL_ID FcnNameId;
  429.   {
  430.   CHAR msg[128];
  431.   CHAR *FcnName;
  432.  
  433.   FcnName = ConvertSymbolToName( FcnNameId );
  434.   if( FcnName )
  435.     {
  436.     S_SPRINTF( msg, "Function %s undefined.", FcnName );
  437.     yyerror( msg );
  438.     }
  439.   }
  440.  
  441. LOCAL VOID ErrArgMismatch( FcnNameId, NumArgsExpected, ActualNumArgs )
  442.   SYMBOL_ID FcnNameId;
  443.   INT NumArgsExpected, ActualNumArgs;
  444.   {
  445.   CHAR msg[128];
  446.   CHAR *FcnName;
  447.  
  448.   FcnName = ConvertSymbolToName( FcnNameId );
  449.   if( FcnName )
  450.     {
  451.     S_SPRINTF( msg,
  452.          "Wrong number of arguments for %s; expected %d, got %d.",
  453.          FcnName, NumArgsExpected, ActualNumArgs );
  454.     yyerror( msg );
  455.     yyerror( "Function call replaced with a constant zero." );
  456.     }
  457.   }
  458.  
  459. /*--------------------------------------------------------------*/
  460. /*        Get a function from the table            */
  461. /*--------------------------------------------------------------*/
  462. typedef struct
  463.   {
  464.   CHAR *name;
  465.   FCN fcn;
  466.   INT numargs;
  467.   } FUN_DESC;
  468.  
  469. #include "FDSevalfuns.h" /* Function definitions and table setup */
  470.  
  471. LOCAL VOID GetFcn( name, fcn, numargs )
  472.   SYMBOL_ID name;
  473.   FCN *fcn;
  474.   INT *numargs;
  475.   {
  476.   INT i;
  477.  
  478.   *numargs = 0;
  479.   *fcn = (FCN)0;
  480.   for( i=0; i<NUMFCNS; i++ )
  481.     if( name == ConvertNameToSymbol( FcnTable[i].name ) )
  482.       {
  483.       *fcn = FcnTable[i].fcn;
  484.       *numargs = FcnTable[i].numargs;
  485.       return;
  486.       }
  487.   }
  488.  
  489. CHAR *GetFcnName( fcn )
  490.   FCN fcn;
  491.   {
  492.   INT i;
  493.  
  494.   for( i=0; i<NUMFCNS; i++ )
  495.     if( fcn == FcnTable[i].fcn ) return FcnTable[i].name;
  496.  
  497.   return (CHAR*)0;
  498.   }
  499.  
  500. /*--------------------------------------------------------------*/
  501. /*             Functions for use in expressions            */
  502. /*--------------------------------------------------------------*/
  503. LOCAL DOUBLE mult( a, b )   DOUBLE a,b;    { return a * b; }
  504. LOCAL DOUBLE divide( a, b )
  505.   DOUBLE a,b;
  506.   {
  507.   if( b != 0.0 )
  508.     return (a/b);
  509.   else
  510.     {
  511.     PrintErrString("Divide by zero");
  512.     return 0.0;
  513.     }
  514.   }
  515. LOCAL DOUBLE add( a, b )    DOUBLE a,b;    { return a + b; }
  516. LOCAL DOUBLE mod( a, b )    DOUBLE a,b;    { return (DOUBLE)((INT)a % (INT)b);}
  517. LOCAL DOUBLE minus( a, b )  DOUBLE a,b;    { return a - b; }
  518. LOCAL DOUBLE neg( a )        DOUBLE a;    { return -a; }
  519.  
  520. LOCAL DOUBLE EQtest( a, b ) DOUBLE a,b;    { return (a == b) ? 1 : 0; }
  521. LOCAL DOUBLE NEtest( a, b ) DOUBLE a,b;    { return (a != b) ? 1 : 0; }
  522. LOCAL DOUBLE LTtest( a, b ) DOUBLE a,b;    { return (a < b) ? 1 : 0; }
  523. LOCAL DOUBLE LEtest( a, b ) DOUBLE a,b;    { return (a <= b) ? 1 : 0; }
  524. LOCAL DOUBLE GTtest( a, b ) DOUBLE a,b;    { return (a > b) ? 1 : 0; }
  525. LOCAL DOUBLE GEtest( a, b ) DOUBLE a,b;    { return (a >= b) ? 1 : 0; }
  526.  
  527. LOCAL DOUBLE cond( a, b, c ) DOUBLE a,b,c; { return (a != 0) ? b : c; }
  528.  
  529.  
  530. /*---------------------------------------------------------------- */
  531. /* Assigns the value of an expression to an address
  532.     ASSUMES the GlobalEnv.CurrentNode->params has the destination address
  533. */
  534. LOCAL DOUBLE assign( a )
  535.   DOUBLE a;
  536.   {
  537.   if( GlobalEnv.CurrentNode->params )
  538.     *((DOUBLE*)GlobalEnv.CurrentNode->params) = a;
  539.   return a;
  540.   }
  541.  
  542. /*---------------------------------------------------------------- */
  543. /* Assigns the value of an expression into a dsvar's data area
  544.    ASSUMES the GlobalEnv.CurrentNode->params has the argument index
  545.    argindex of the destination dsv
  546. */
  547. LOCAL DOUBLE assign_to_dsv( a )
  548.   DOUBLE a;
  549.   {
  550.   if( GlobalEnv.CurrentNode->params )
  551.     {
  552.     DV_BOOL result;
  553.     INT argindex, argtype;
  554.     ANYTYPE arg;
  555.     
  556.     /* If the argindex refers to a data source variable, then assign */
  557.     /* the value to it. */
  558.     argindex = (INT)GlobalEnv.CurrentNode->params;
  559.  
  560.     /* Get the argindex-th argument */
  561.     switch( GlobalEnv.FdsFunType )
  562.       {
  563.     case V_FDS_FCN_OPEN:
  564.     case V_FDS_FCN_READ:
  565.       result = TdsGetFcnArg( M_dscurrent, GlobalEnv.FdsFunType, argindex+1,
  566.                 &argtype, &arg );
  567.       break;
  568.     case V_FDS_FCN_SELECT:
  569.       result = TdsvGetFcnArg( M_dsvcurrent, GlobalEnv.FdsFunType, argindex+1,
  570.                  &argtype, &arg );
  571.       break;
  572.     default:
  573.       return (DOUBLE)0;
  574.       }
  575.     
  576.     if( result == DV_SUCCESS && argtype == V_DSV_TYPE )
  577.       TdsvSetValue( arg.ptr, a, 0, 0 );
  578.     }
  579.   
  580.   return a;
  581.   }
  582.  
  583. /*---------------------------------------------------------------- */
  584. /* Reads the value of a symbol
  585.    ASSUMES the GlobalEnv.CurrentNode->params has the symbol value's address
  586. */
  587. LOCAL DOUBLE readsym()
  588.   {
  589.   if( GlobalEnv.CurrentNode->params )
  590.     return *((DOUBLE*)GlobalEnv.CurrentNode->params);
  591.   else return 0;
  592.   }
  593.  
  594. /*---------------------------------------------------------------- */
  595. /* Gets the value from a data source variable or other FDS arg
  596.    Assumes the parameter field has been setup with the argument
  597.    index.  This must resolve the argument each time in case users
  598.    have rebound the data source arguments.
  599. */
  600. LOCAL DOUBLE readvar()
  601.   {
  602.   DV_BOOL result;
  603.   INT argindex, argtype;
  604.   ANYTYPE arg;
  605.  
  606.   argindex = (INT)GlobalEnv.CurrentNode->params;
  607.   switch( GlobalEnv.FdsFunType )
  608.     {
  609.   case V_FDS_FCN_OPEN:
  610.   case V_FDS_FCN_READ:
  611.     result = TdsGetFcnArg( M_dscurrent, GlobalEnv.FdsFunType, argindex+1,
  612.                &argtype, &arg );
  613.     break;
  614.   case V_FDS_FCN_SELECT:
  615.     result = TdsvGetFcnArg( M_dsvcurrent, GlobalEnv.FdsFunType,argindex+1,
  616.                &argtype, &arg );
  617.     break;
  618.   default:
  619.     return (DOUBLE)0;
  620.     }
  621.  
  622.   if( result == DV_SUCCESS )
  623.     {
  624.     INT datatype;
  625.     ADDRESS databuf;
  626.     
  627.     switch( argtype )
  628.       {
  629.     case V_DSV_TYPE: /* Argument is a data source variable */
  630.       databuf = TdsvGetBuffer( arg.ptr );
  631.       datatype = TdsvGetType( arg.ptr );
  632.       
  633.       /* Read its data buffer, looking at its type */
  634.       switch( datatype )
  635.     {
  636.       case V_C_TYPE:    return (DOUBLE)(*(CHAR*)databuf);
  637.       case V_UC_TYPE:    return (DOUBLE)(*(UBYTE*)databuf);
  638.       case V_S_TYPE:    return (DOUBLE)(*(SHORT*)databuf);
  639.       case V_US_TYPE:    return (DOUBLE)(*(USHORT*)databuf);
  640.       case V_L_TYPE:    return (DOUBLE)(*(LONG*)databuf);
  641.       case V_UL_TYPE:    return (DOUBLE)(*(ULONG*)databuf);
  642.       case V_F_TYPE:    return (DOUBLE)(*(FLOAT*)databuf);
  643.       case V_D_TYPE:    return *(DOUBLE*)databuf;
  644.       case V_T_TYPE:    return StringToDouble((CHAR*)databuf);
  645.     }
  646.       
  647.     case V_L_TYPE: /* Argument is a long constant */
  648.       return (DOUBLE)arg.l;
  649.       
  650.     case V_D_TYPE: /* Argument is a double constant */
  651.       return (DOUBLE)arg.d;
  652.       
  653.     case V_T_TYPE: /* Argument is a string constant */
  654.       /* Try to read the string as a double */
  655.       return StringToDouble(arg.ptr);
  656.       
  657.     default:
  658.     case V_NULL_TYPE: /* Unknown or null argument */
  659.       return (DOUBLE)0;
  660.       }
  661.     }
  662.   
  663.   return (DOUBLE)0;
  664.   }
  665.  
  666. /*--------------------------------------------------------------*/
  667. /*         Parse tree handling functions            */
  668. /*--------------------------------------------------------------*/
  669. /*
  670. |    Module description/function:
  671. |
  672. |              These routines manage the creation, traversal and
  673. |    destruction of an expression parse tree.  A parse tree
  674. |    is a linked set of parse tree nodes (PTN), where each node
  675. |    has a function for evaluating the value of the node,
  676. |    which takes the value of up to MAX_SUBTREES subtree nodes
  677. |    as arguments.
  678. |
  679. | ------------------------------------------------------------------
  680. |    Module contents:
  681. |    Name         Description
  682. |    -------    -------------------------------
  683. |    PTNcreate    Creates a new parse tree node
  684. |    PTNdestroy    Destroys a parse tree node and all its subnodes.
  685. |    PTNeval    Get the value of a parse tree node.
  686. |    PTNsetParam     Set parameter field for node.
  687. |    PTNgetParam    Get parameter field for node.
  688. #ifdef DEBUG
  689. |    PTNprint    Print a subtree
  690. #endif
  691. |
  692. |====================================================================
  693. */
  694.  
  695. /*-----------------------------------------------------------------*/
  696. LOCAL NODE *PTNcreate( value, fcn, sub1, sub2, sub3 )
  697.   DOUBLE value;
  698.   FCN fcn;
  699.   NODE *sub1, *sub2, *sub3;
  700.   {
  701.   NODE *new;
  702.  
  703.   new = (NODE*)S_ALLOC( sizeof(NODE) );
  704.   new->value = value;
  705.   new->fcn = fcn;
  706.   new->params = (ADDRESS)0;
  707.   new->FreeParams = (VOID(*)())0;
  708.  
  709.   /* Assign the subtree arguments */
  710.   new->Subtree[0] = sub1;
  711.   new->Subtree[1] = sub2;
  712.   new->Subtree[2] = sub3;
  713.  
  714.   return new;
  715.   }
  716.  
  717. /*-----------------------------------------------------------------*/
  718. LOCAL VOID PTNdestroy( ptn )
  719.   NODE *ptn;
  720.   {
  721.   if( ptn->params && ptn->FreeParams)
  722.     (*ptn->FreeParams)( ptn->params );
  723.   if( ptn->Subtree[0] ) PTNdestroy( ptn->Subtree[0] );
  724.   if( ptn->Subtree[1] ) PTNdestroy( ptn->Subtree[1] );
  725.   if( ptn->Subtree[2] ) PTNdestroy( ptn->Subtree[2] );
  726.   S_FREE( (ADDRESS)ptn );
  727.   }
  728.  
  729. /*-----------------------------------------------------------------*/
  730. LOCAL DOUBLE PTNeval( ptn )
  731.   NODE *ptn;
  732.   {
  733.   INT i;
  734.   DOUBLE r[MAX_SUBTREES];
  735.  
  736.   if( ptn->fcn )
  737.     {
  738.     /* Handle the conditional expression (exp?exp:exp) as a special case */
  739.     /* Only evaluate the subtrees if it is necessary. */
  740.     if( ptn->fcn == cond )
  741.       {
  742.       /* For a conditional function, evaluate the "if" part (the condition) */
  743.       /* and then evaluate the appropriate "then" or "else" subtree.        */
  744.       if( 0.0 != PTNeval( ptn->Subtree[0] ) )
  745.     ptn->value = PTNeval( ptn->Subtree[1] ); /* True part */
  746.       else
  747.     ptn->value = PTNeval( ptn->Subtree[2] ); /* False part */
  748.       }
  749.     else
  750.       { /* Not a conditional expression */
  751.       /* Evaluate each relevant subtree */
  752.       for( i=0; i<MAX_SUBTREES; i++ )
  753.     if( ptn->Subtree[i] )
  754.       r[i] = PTNeval( ptn->Subtree[i] );
  755.     else
  756.       break;
  757.       
  758.       /* Set global variable that defines the current node */
  759.       GlobalEnv.CurrentNode = ptn;
  760.       
  761.       /* Evaluate the function */
  762.       switch( i )
  763.     {
  764.       case 0: ptn->value = (*ptn->fcn)(); break;
  765.       case 1: ptn->value = (*ptn->fcn)( r[0] ); break;
  766.       case 2: ptn->value = (*ptn->fcn)( r[0],r[1] ); break;
  767.       case 3: ptn->value = (*ptn->fcn)( r[0],r[1],r[2] ); break;
  768.       case 4: ptn->value = (*ptn->fcn)( r[0],r[1],r[2],r[3] ); break;
  769.     };
  770.       }
  771.     }
  772.   
  773.   return ptn->value;
  774.   }
  775.  
  776. /*-----------------------------------------------------------------*/
  777. #ifdef DEBUG
  778. LOCAL VOID PTNprint( ptn, depth )
  779.   NODE *ptn;
  780.   INT depth;
  781.   {
  782.   INT i;
  783.  
  784.   for( i=depth; i>0; i-- ) (VOID)S_PRINTF( " | " );
  785.   (VOID)S_PRINTF( "Node: 0x%x; Value: %f; Function: 0x%x (%s)\n",
  786.          ptn, ptn->value, ptn->fcn, GetFcnName(ptn->fcn) );
  787.  
  788.   for( i=0; i<MAX_SUBTREES; i++ )
  789.     if( ptn->Subtree[i] ) PTNprint( ptn->Subtree[i], depth+1 );
  790.   }
  791. #endif
  792.  
  793. /*--------------------------------------------------------------*/
  794. /*         FUNCTION DATA SOURCE for expression evaluation    */
  795. /*--------------------------------------------------------------*/
  796.  
  797. GLOBALREF ADDRESS M_dsvcurrent;
  798. GLOBALREF ADDRESS M_dscurrent;
  799.  
  800. /*--------------------------------------------------------------*/
  801. /*  ExpListCreate */
  802. LOCAL EXPRESSION* ExpListCreate( exp )
  803.   CHAR *exp;
  804.   {
  805.   INT slen;
  806.   EXPRESSION *ElistStart = 0, *Enode;
  807.  
  808.   DV_INIT( Enode, (EXPRESSION *)0 );
  809.   /*
  810.   The expression to be parsed is passed to the parser 
  811.   using static variables: 
  812.     expression    is a (CHAR*) that steps through the string.
  813.     ExpStart      points to the start of the string.
  814.     ParseResult   gets the result of the parse
  815.     CurrentParams has other info, including the symbol table.
  816.   */
  817.   /* Allocate a string and add the terminator character ';' */
  818.   slen = S_STRLEN( exp );
  819.   ExpStart = S_ALLOC( (slen+2) * (LONG)sizeof(CHAR) );
  820.   (VOID)S_STRNCPY( ExpStart, exp, slen );
  821.   ExpStart[slen] = ';';
  822.   ExpStart[slen+1] =  '\0';
  823.   expression = ExpStart;
  824.  
  825.   while( *expression )
  826.     {
  827.     ParseResult = 0;
  828.     if( 0 == yyparse() )
  829.       {
  830.       if( ParseResult )
  831.     { /* We have a valid parse tree */
  832.     if( ElistStart == 0 )
  833.       /* Start the list */
  834.       Enode = ElistStart = (EXPRESSION*)S_ALLOC( sizeof(EXPRESSION) );
  835.     else
  836.       { /* Add it to the end of the current list */
  837.       Enode->next = (EXPRESSION*)S_ALLOC( sizeof(EXPRESSION) );
  838.       Enode = Enode->next;
  839.       }
  840.     Enode->next = (struct expstruct*)0;
  841.     Enode->exp = ParseResult;
  842.     }
  843.       /* else; No parse tree generated for this part of the expression */
  844.       }
  845.     else
  846.       { /* Parse failed; create a '0' generator, if no expression so far */
  847.       if( ParseResult ) PTNdestroy( ParseResult );
  848.       if( ElistStart == 0) 
  849.     {
  850.     ElistStart = (EXPRESSION*)S_ALLOC( sizeof(EXPRESSION) );
  851.     ElistStart->next = (struct expstruct*)0;
  852.     ElistStart->exp =
  853.       PTNcreate( (DOUBLE)0,(FCN)0,(NODE*)0,(NODE*)0,(NODE*)0 );
  854.     }
  855.       break;
  856.       }
  857.     }
  858.  
  859.   S_FREE( (ADDRESS)ExpStart );
  860.   return ElistStart;
  861.   }
  862.  
  863. /*--------------------------------------------------------------*/
  864. /*  Destroy an expression list */
  865. LOCAL VOID ExpListDestroy( ExpList )
  866.   EXPRESSION *ExpList; /* Linked list of expressions */
  867.   {
  868.   EXPRESSION *ExpNext;
  869.  
  870.   while( ExpList )
  871.     {
  872.     ExpNext = ExpList->next;
  873.     PTNdestroy( ExpList->exp );
  874.     S_FREE( (ADDRESS)ExpList );
  875.     ExpList = ExpNext;
  876.     }
  877.   }
  878.  
  879. /*--------------------------------------------------------------*/
  880. /*  Evaluate and expression list */
  881. LOCAL VOID ExpListEval( ExpList )
  882.   EXPRESSION *ExpList; /* Linked list of expressions */
  883.   {
  884.   /* Evaluate each expression. The data source ends up with the result */
  885.   /* of the last expression. */
  886.   for( ; ExpList; ExpList = ExpList->next )
  887.     TdsvSetValue( M_dsvcurrent, (DOUBLE)PTNeval(ExpList->exp), 0, 0 );
  888.   }
  889.  
  890. /*--------------------------------------------------------------*/
  891. /*--------------------------------------------------------------*/
  892. LOCAL LONG evalinit V_P_ ((CHAR *, V_FDS_OPT_ARG *));
  893.  
  894. V_FDS_FCN_DECL( V_FDS_FCN_OPEN, evalinitdesc, evalinit, "Initialize" )
  895.     V_FDS_TEXT_ARG_DECL( "Initial eqs", "i=0" )
  896. V_FDS_END_FCN_DECL
  897. LOCAL LONG evalinit( exp, opt_args )
  898.   CHAR *exp;
  899.   V_FDS_OPT_ARG *opt_args; 
  900.   {
  901.   EVAL_PARAMS *ep;
  902.   EXPRESSION *ExpList, *Enode;
  903. #ifndef RS6000
  904. #ifndef DV_DEV_COMP
  905.   int strcmp();
  906. #endif
  907. #endif
  908.  
  909.   ep = (EVAL_PARAMS*)S_ALLOC( sizeof(EVAL_PARAMS) );
  910.   if( ep == NULL ) return DV_FAILURE;
  911.  
  912.   ep->read_explist = 0; /* Common expression list to be evaluated by read */
  913.   ep->data_area = daCreate();
  914.  
  915.   (VOID)TdsSetAuxData( M_dscurrent, (ADDRESS)ep, (TDSFREEFUNPTR)0 );
  916.  
  917.   /* If there is an initialization expression, evaluate it */
  918.   /* The evaluation primes the symbol table as a side effect */
  919.   if( exp )
  920.     {
  921.     CurrentParams = ep;
  922.  
  923.     /* Set up part of global env that describes what invoked evaluation */
  924.     GlobalEnv.FdsFunType = V_FDS_FCN_OPEN;
  925.     GlobalEnv.CurrentFunction = "Data Source OPEN";
  926.  
  927.     /* Parse the expression */
  928.     ExpList = ExpListCreate( exp );
  929.  
  930.     /* Evaluate the expression */
  931.     for( Enode = ExpList; Enode; Enode = Enode->next )
  932.       (VOID)PTNeval(Enode->exp);
  933.  
  934.     ExpListDestroy( ExpList );
  935.     }
  936.  
  937.   return DV_SUCCESS;
  938.   }
  939.  
  940. /*--------------------------------------------------------------*/
  941. LOCAL VOID evalterm V_P_ ((void));
  942. V_FDS_FCN_DECL( V_FDS_FCN_CLOSE, evaltermdesc, evalterm, "Terminate" )
  943. V_FDS_END_FCN_DECL
  944. LOCAL VOID evalterm()
  945.   {
  946.   EVAL_PARAMS *ep;
  947.   
  948.   ep = (EVAL_PARAMS*)TdsGetAuxData( M_dscurrent );
  949.   if( ep->read_explist )
  950.     ExpListDestroy( ep->read_explist );
  951.   daDestroy( ep->data_area );
  952.   S_FREE((ADDRESS)ep);
  953.   }
  954.  
  955. /*--------------------------------------------------------------*/
  956. LOCAL LONG evalread V_P_ ((CHAR *, V_FDS_OPT_ARG *));
  957. V_FDS_FCN_DECL( V_FDS_FCN_READ, evalreaddesc, evalread, "Read" )
  958.     V_FDS_TEXT_ARG_DECL( "Update eqs", "i=i+1" )
  959. V_FDS_END_FCN_DECL
  960. LOCAL LONG evalread( exp, opt_args )
  961.   CHAR *exp;
  962.   V_FDS_OPT_ARG *opt_args; 
  963.   {
  964.   EXPRESSION *Enode;
  965.   
  966.   /* Set up part of global environment that describes */
  967.   /* what invoked the evaluation */
  968.   GlobalEnv.FdsFunType = V_FDS_FCN_READ;
  969.   GlobalEnv.CurrentFunction = "Data Source READ";
  970.  
  971.   CurrentParams = (EVAL_PARAMS*)TdsGetAuxData( M_dscurrent );
  972.   if( exp && CurrentParams->read_explist == NULL )
  973.     {
  974.     /* Parse the expression */
  975.     CurrentParams->read_explist = ExpListCreate( exp );
  976.     }
  977.  
  978.   /* Evaluate the expression */
  979.   for( Enode = CurrentParams->read_explist; Enode; Enode = Enode->next )
  980.     (VOID)PTNeval(Enode->exp);
  981.  
  982.   /* always return SUCSSESS, DV_FAILURE means to simulate an EOF */
  983.   return DV_SUCCESS;
  984.   }
  985.  
  986. /*--------------------------------------------------------------*/
  987. /*        FDS SELECT functions                */
  988. /*--------------------------------------------------------------*/
  989.  
  990. /*--------------------------------------------------------------*/
  991. /* EvalString - String expression evaluator            */
  992. /*
  993. The argument is an expression string followed by a number of
  994. values that replace parts of the string.  This supports optional
  995. arguments of type expr_arg, which replace symbols of the form $n,
  996. where n is in the range [0-9].
  997. */
  998. LOCAL LONG EvalString V_P_ ((CHAR *, V_FDS_OPT_ARG *));
  999.  
  1000. V_FDS_FCN_DECL( V_FDS_FCN_SELECT, evaldesc, EvalString, "Eval String" )
  1001.     V_FDS_TEXT_ARG_DECL( "expression", "wnoise()" )
  1002. V_FDS_END_FCN_DECL
  1003. LOCAL LONG EvalString( exp, opt_args )
  1004.   CHAR *exp;
  1005.   V_FDS_OPT_ARG *opt_args; 
  1006.   {
  1007.   EXPRESSION *ExpList;
  1008.   
  1009.   /* If this is the first time that the routine has been called */
  1010.   /* then parse the expressions and save the parse trees */
  1011.   ExpList = (EXPRESSION*)TdsvGetAuxData( M_dsvcurrent );
  1012.   if( ExpList == NULL )
  1013.     { 
  1014.     /* Parse the expression and save it with the data source. */
  1015.     ExpList = ExpListCreate( exp );
  1016.     if( ExpList )
  1017.       (VOID)TdsvSetAuxData( M_dsvcurrent,
  1018.                 (ADDRESS)ExpList, (TDSFREEFUNPTR)ExpListDestroy );
  1019.     }
  1020.  
  1021.   /* Set up part of global environment that describes */
  1022.   /* what invoked the evaluation */
  1023.   GlobalEnv.FdsFunType = V_FDS_FCN_SELECT;
  1024.   ExpListEval( ExpList );
  1025.  
  1026.   /* always return DV_SUCCESS, DV_FAILURE would simulate an EOF */
  1027.   return DV_SUCCESS;
  1028.   }
  1029.  
  1030. /*--------------------------------------------------------------*/
  1031. /* GetDsvValue - Gets value from a data source into a symbol    */
  1032. LOCAL LONG GetDsvValue V_P_ ((CHAR *, ADDRESS, ADDRESS));
  1033.  
  1034. V_FDS_FCN_DECL( V_FDS_FCN_SELECT, getdsvdesc, GetDsvValue, 
  1035.            "Read Data Source Value" )
  1036.     V_FDS_TEXT_ARG_DECL( "expression", "$1 + $2" )
  1037.     V_FDS_DSVAR_ARG_DECL( "Value $1" )
  1038.     V_FDS_DSVAR_ARG_DECL( "Value $2" )
  1039. V_FDS_END_FCN_DECL
  1040. LOCAL LONG GetDsvValue( exp, dsvar1, dsvar2 )
  1041.   CHAR *exp;
  1042.   ADDRESS dsvar1, dsvar2;
  1043.   {
  1044.   EXPRESSION *ExpList;
  1045.  
  1046.   /* If this is the first time that the routine has been called */
  1047.   /* then parse the expressions and save the parse trees */
  1048.   ExpList = (EXPRESSION*)TdsvGetAuxData( M_dsvcurrent );
  1049.   if( ExpList == NULL )
  1050.     { 
  1051.     ExpList = ExpListCreate( exp );
  1052.     if( ExpList )
  1053.       (VOID)TdsvSetAuxData( M_dsvcurrent,
  1054.                (ADDRESS)ExpList, (TDSFREEFUNPTR)ExpListDestroy ); 
  1055.     }
  1056.  
  1057.   /* Set up part of global environment that describes */
  1058.   /* what invoked the evaluation */
  1059.   GlobalEnv.FdsFunType = V_FDS_FCN_SELECT;
  1060.   ExpListEval( ExpList );
  1061.  
  1062.   /* always return SUCSSESS, DV_FAILURE means to simulate an EOF */
  1063.   return DV_SUCCESS;
  1064.   }
  1065.  
  1066. /*--------------------------------------------------------------*/
  1067. V_FDS_START_DECL( FDSeval )
  1068.   V_FDS_FCN_DEFINED( evalinitdesc )
  1069.   V_FDS_FCN_DEFINED( evaltermdesc )
  1070.   V_FDS_FCN_DEFINED( evalreaddesc )
  1071.   V_FDS_FCN_DEFINED( evaldesc )
  1072.   V_FDS_FCN_DEFINED( getdsvdesc )
  1073. V_FDS_END_DECL
  1074. int yyexca[] ={
  1075. -1, 1,
  1076.     0, -1,
  1077.     -2, 0,
  1078.     };
  1079. # define YYNPROD 31
  1080. # define YYLAST 311
  1081. int yyact[]={
  1082.  
  1083.     26,    28,    27,    25,    57,    23,    21,    58,    22,    26,
  1084.     24,    29,     7,    53,    23,    21,    54,    22,    31,    24,
  1085.      8,     1,     0,    26,     0,    10,    14,    60,    23,    21,
  1086.      9,    22,    26,    24,     0,    14,    26,    23,    21,    30,
  1087.     22,     0,    24,     0,     0,     0,    26,     0,     0,    14,
  1088.     51,    23,    21,    52,    22,    26,    24,    25,    14,    26,
  1089.     23,    21,     0,    22,    23,    24,    25,     0,    26,    24,
  1090.     10,    49,    14,    23,    21,     9,    22,    26,    24,     0,
  1091.     25,    14,    23,    21,     0,    22,     0,    24,     0,    25,
  1092.      0,    10,    26,    25,    14,     0,     9,    23,    21,     0,
  1093.     22,     0,    24,    25,     0,     0,     0,     0,     0,     0,
  1094.      0,     0,    25,     0,     0,     0,    25,     0,     0,     0,
  1095.      3,     0,     0,     0,     0,    25,     0,     0,     0,     0,
  1096.     32,    33,     0,     0,    25,    34,    35,    36,    37,    38,
  1097.     39,    40,    41,    42,    43,    44,    45,    46,     0,    25,
  1098.     47,    48,    50,     0,     0,     0,     0,     0,     0,     0,
  1099.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  1100.      0,     0,     0,    55,     0,    56,     0,     0,     0,    59,
  1101.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  1102.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  1103.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  1104.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  1105.      0,     0,     0,     0,     0,    16,    15,    19,    17,    20,
  1106.     18,     0,     0,     0,    16,    15,    19,    17,    20,    18,
  1107.      0,     5,    11,    12,     6,     2,     4,     0,    16,    15,
  1108.     19,    17,    20,    18,     0,     0,     0,    16,    15,    19,
  1109.     17,    20,    18,     0,     0,     0,     0,     0,     0,     0,
  1110.      0,    16,    15,    19,    17,    20,    18,     0,    13,     0,
  1111.     16,    15,    19,    17,    20,    18,     0,    11,    12,     6,
  1112.      0,     0,     0,    16,    15,    19,    17,    20,    18,     0,
  1113.      0,     0,     0,     0,    19,    17,    20,    18,    11,    12,
  1114.      6 };
  1115. int yypact[]={
  1116.  
  1117.    -15, -1000, -1000,    18,  -258,  -259, -1000,   -50,   -22,    51,
  1118.     51, -1000, -1000, -1000,    51,    51,    51,    51,    51,    51,
  1119.     51,    51,    51,    51,    51,    51,    51, -1000, -1000,    51,
  1120.     51,    30,   -91,     9,    -5,    40,    40,    55,    55,    55,
  1121.     55,    22,    22,    -1,    -1,   -91,   -91,    31,    31, -1000,
  1122.    -28, -1000,    51, -1000,    51,    31,   -37, -1000,    51,   -14,
  1123.  -1000 };
  1124. int yypgo[]={
  1125.  
  1126.      0,    21,   120,    20,    12 };
  1127. int yyr1[]={
  1128.  
  1129.      0,     1,     1,     1,     1,     3,     4,     2,     2,     2,
  1130.      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
  1131.      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
  1132.      2 };
  1133. int yyr2[]={
  1134.  
  1135.      0,     3,     5,     5,     5,     3,     3,     3,     3,     7,
  1136.      7,    11,     7,     9,    13,    17,     3,     7,     7,     7,
  1137.      7,     7,     7,     7,     7,     7,     7,     5,     7,     7,
  1138.      7 };
  1139. int yychk[]={
  1140.  
  1141.  -1000,    -1,   260,    -2,   261,   256,   259,    -4,    -3,    45,
  1142.     40,   257,   258,   260,    63,   263,   262,   265,   267,   264,
  1143.    266,    43,    45,    42,    47,    94,    37,   260,   260,    61,
  1144.     61,    40,    -2,    -2,    -2,    -2,    -2,    -2,    -2,    -2,
  1145.     -2,    -2,    -2,    -2,    -2,    -2,    -2,    -2,    -2,    41,
  1146.     -2,    41,    58,    41,    44,    -2,    -2,    41,    44,    -2,
  1147.     41 };
  1148. int yydef[]={
  1149.  
  1150.      0,    -2,     1,     0,     0,     0,     7,     8,    16,     0,
  1151.      0,     6,     5,     2,     0,     0,     0,     0,     0,     0,
  1152.      0,     0,     0,     0,     0,     0,     0,     3,     4,     0,
  1153.      0,     0,    27,     0,     0,    17,    18,    19,    20,    21,
  1154.     22,    23,    24,    25,    26,    28,    29,    10,     9,    12,
  1155.      0,    30,     0,    13,     0,    11,     0,    14,     0,     0,
  1156.     15 };
  1157. typedef struct { char *t_name; int t_val; } yytoktype;
  1158. #ifndef YYDEBUG
  1159. #    define YYDEBUG    0    /* don't allow debugging */
  1160. #endif
  1161.  
  1162. #if YYDEBUG
  1163.  
  1164. yytoktype yytoks[] =
  1165. {
  1166.     "EXPR_ARG_MARKER",    257,
  1167.     "ID",    258,
  1168.     "EVAL_NUMBER",    259,
  1169.     "TERMINATOR",    260,
  1170.     "INCLUDE_FILE",    261,
  1171.     "EQ",    262,
  1172.     "NE",    263,
  1173.     "LE",    264,
  1174.     "GE",    265,
  1175.     "LT",    266,
  1176.     "GT",    267,
  1177.     "=",    61,
  1178.     "?",    63,
  1179.     ":",    58,
  1180.     "+",    43,
  1181.     "-",    45,
  1182.     "*",    42,
  1183.     "/",    47,
  1184.     "%",    37,
  1185.     "!",    33,
  1186.     "NEG",    268,
  1187.     "^",    94,
  1188.     "-unknown-",    -1    /* ends search */
  1189. };
  1190.  
  1191. char * yyreds[] =
  1192. {
  1193.     "-no such reduction-",
  1194.     "stmt : TERMINATOR",
  1195.     "stmt : exp TERMINATOR",
  1196.     "stmt : INCLUDE_FILE TERMINATOR",
  1197.     "stmt : error TERMINATOR",
  1198.     "symbol : ID",
  1199.     "arg : EXPR_ARG_MARKER",
  1200.     "exp : EVAL_NUMBER",
  1201.     "exp : arg",
  1202.     "exp : symbol '=' exp",
  1203.     "exp : arg '=' exp",
  1204.     "exp : exp '?' exp ':' exp",
  1205.     "exp : symbol '(' ')'",
  1206.     "exp : symbol '(' exp ')'",
  1207.     "exp : symbol '(' exp ',' exp ')'",
  1208.     "exp : symbol '(' exp ',' exp ',' exp ')'",
  1209.     "exp : symbol",
  1210.     "exp : exp NE exp",
  1211.     "exp : exp EQ exp",
  1212.     "exp : exp GE exp",
  1213.     "exp : exp GT exp",
  1214.     "exp : exp LE exp",
  1215.     "exp : exp LT exp",
  1216.     "exp : exp '+' exp",
  1217.     "exp : exp '-' exp",
  1218.     "exp : exp '*' exp",
  1219.     "exp : exp '/' exp",
  1220.     "exp : '-' exp",
  1221.     "exp : exp '^' exp",
  1222.     "exp : exp '%' exp",
  1223.     "exp : '(' exp ')'",
  1224. };
  1225. #endif /* YYDEBUG */
  1226. /*    @(#)yaccpar 1.10 89/04/04 SMI; from S5R3 1.10    */
  1227.  
  1228. /*
  1229. ** Skeleton parser driver for yacc output
  1230. */
  1231.  
  1232. /*
  1233. ** yacc user known macros and defines
  1234. */
  1235. #define YYERROR        goto yyerrlab
  1236. #define YYACCEPT    { free(yys); free(yyv); return(0); }
  1237. #define YYABORT        { free(yys); free(yyv); return(1); }
  1238. #define YYBACKUP( newtoken, newvalue )\
  1239. {\
  1240.     if ( yychar >= 0 || ( yyr2[ yytmp ] >> 1 ) != 1 )\
  1241.     {\
  1242.         yyerror( "syntax error - cannot backup" );\
  1243.         goto yyerrlab;\
  1244.     }\
  1245.     yychar = newtoken;\
  1246.     yystate = *yyps;\
  1247.     yylval = newvalue;\
  1248.     goto yynewstate;\
  1249. }
  1250. #define YYRECOVERING()    (!!yyerrflag)
  1251. #ifndef YYDEBUG
  1252. #    define YYDEBUG    1    /* make debugging available */
  1253. #endif
  1254.  
  1255. /*
  1256. ** user known globals
  1257. */
  1258. int yydebug;            /* set to 1 to get debugging */
  1259.  
  1260. /*
  1261. ** driver internal defines
  1262. */
  1263. #define YYFLAG        (-1000)
  1264.  
  1265. /*
  1266. ** static variables used by the parser
  1267. */
  1268. static YYSTYPE *yyv;            /* value stack */
  1269. static int *yys;            /* state stack */
  1270.  
  1271. static YYSTYPE *yypv;            /* top of value stack */
  1272. static int *yyps;            /* top of state stack */
  1273.  
  1274. static int yystate;            /* current state */
  1275. static int yytmp;            /* extra var (lasts between blocks)*/
  1276.  
  1277. int yynerrs;            /* number of errors */
  1278.  
  1279. int yyerrflag;            /* error recovery flag */
  1280. int yychar;            /* current input token number */
  1281.  
  1282.  
  1283. /*
  1284. ** yyparse - return 0 if worked, 1 if syntax error not recovered from
  1285. */
  1286. int
  1287. yyparse()
  1288. {
  1289.     register YYSTYPE *yypvt;    /* top of value stack for $vars */
  1290.     unsigned yymaxdepth = YYMAXDEPTH;
  1291.  
  1292.     /*
  1293.     ** Initialize externals - yyparse may be called more than once
  1294.     */
  1295.     yyv = (YYSTYPE*)malloc(yymaxdepth*sizeof(YYSTYPE));
  1296.     yys = (int*)malloc(yymaxdepth*sizeof(int));
  1297.     if (!yyv || !yys)
  1298.     {
  1299.         yyerror( "out of memory" );
  1300.         return(1);
  1301.     }
  1302.     yypv = &yyv[-1];
  1303.     yyps = &yys[-1];
  1304.     yystate = 0;
  1305.     yytmp = 0;
  1306.     yynerrs = 0;
  1307.     yyerrflag = 0;
  1308.     yychar = -1;
  1309.  
  1310.     goto yystack;
  1311.     {
  1312.         register YYSTYPE *yy_pv;    /* top of value stack */
  1313.         register int *yy_ps;        /* top of state stack */
  1314.         register int yy_state;        /* current state */
  1315.         register int  yy_n;         /* internal state number info */
  1316.  
  1317.         /*
  1318.         ** get globals into registers.
  1319.         ** branch to here only if YYBACKUP was called.
  1320.         */
  1321.     yynewstate:
  1322.         yy_pv = yypv;
  1323.         yy_ps = yyps;
  1324.         yy_state = yystate;
  1325.         goto yy_newstate;
  1326.  
  1327.         /*
  1328.         ** get globals into registers.
  1329.         ** either we just started, or we just finished a reduction
  1330.         */
  1331.     yystack:
  1332.         yy_pv = yypv;
  1333.         yy_ps = yyps;
  1334.         yy_state = yystate;
  1335.  
  1336.         /*
  1337.         ** top of for (;;) loop while no reductions done
  1338.         */
  1339.     yy_stack:
  1340.         /*
  1341.         ** put a state and value onto the stacks
  1342.         */
  1343. #if YYDEBUG
  1344.         /*
  1345.         ** if debugging, look up token value in list of value vs.
  1346.         ** name pairs.  0 and negative (-1) are special values.
  1347.         ** Note: linear search is used since time is not a real
  1348.         ** consideration while debugging.
  1349.         */
  1350.         if ( yydebug )
  1351.         {
  1352.             register int yy_i;
  1353.  
  1354.             (void)printf( "State %d, token ", yy_state );
  1355.             if ( yychar == 0 )
  1356.                 (void)printf( "end-of-file\n" );
  1357.             else if ( yychar < 0 )
  1358.                 (void)printf( "-none-\n" );
  1359.             else
  1360.             {
  1361.                 for ( yy_i = 0; yytoks[yy_i].t_val >= 0;
  1362.                     yy_i++ )
  1363.                 {
  1364.                     if ( yytoks[yy_i].t_val == yychar )
  1365.                         break;
  1366.                 }
  1367.                 (void)printf( "%s\n", yytoks[yy_i].t_name );
  1368.             }
  1369.         }
  1370. #endif /* YYDEBUG */
  1371.         if ( ++yy_ps >= &yys[ yymaxdepth ] )  /* room on stack? */
  1372.         {
  1373.             /*
  1374.             ** reallocate and recover.  Note that pointers
  1375.             ** have to be reset, or bad things will happen
  1376.             */
  1377.             int yyps_index = (yy_ps - yys);
  1378.             int yypv_index = (yy_pv - yyv);
  1379.             int yypvt_index = (yypvt - yyv);
  1380.             yymaxdepth += YYMAXDEPTH;
  1381.             yyv = (YYSTYPE*)realloc((char*)yyv,
  1382.                 yymaxdepth * sizeof(YYSTYPE));
  1383.             yys = (int*)realloc((char*)yys,
  1384.                 yymaxdepth * sizeof(int));
  1385.             if (!yyv || !yys)
  1386.             {
  1387.                 yyerror( "yacc stack overflow" );
  1388.                 return(1);
  1389.             }
  1390.             yy_ps = yys + yyps_index;
  1391.             yy_pv = yyv + yypv_index;
  1392.             yypvt = yyv + yypvt_index;
  1393.         }
  1394.         *yy_ps = yy_state;
  1395.         *++yy_pv = yyval;
  1396.  
  1397.         /*
  1398.         ** we have a new state - find out what to do
  1399.         */
  1400.     yy_newstate:
  1401.         if ( ( yy_n = yypact[ yy_state ] ) <= YYFLAG )
  1402.             goto yydefault;        /* simple state */
  1403. #if YYDEBUG
  1404.         /*
  1405.         ** if debugging, need to mark whether new token grabbed
  1406.         */
  1407.         yytmp = yychar < 0;
  1408. #endif
  1409.         if ( ( yychar < 0 ) && ( ( yychar = yylex() ) < 0 ) )
  1410.             yychar = 0;        /* reached EOF */
  1411. #if YYDEBUG
  1412.         if ( yydebug && yytmp )
  1413.         {
  1414.             register int yy_i;
  1415.  
  1416.             (void)printf( "Received token " );
  1417.             if ( yychar == 0 )
  1418.                 (void)printf( "end-of-file\n" );
  1419.             else if ( yychar < 0 )
  1420.                 (void)printf( "-none-\n" );
  1421.             else
  1422.             {
  1423.                 for ( yy_i = 0; yytoks[yy_i].t_val >= 0;
  1424.                     yy_i++ )
  1425.                 {
  1426.                     if ( yytoks[yy_i].t_val == yychar )
  1427.                         break;
  1428.                 }
  1429.                 (void)printf( "%s\n", yytoks[yy_i].t_name );
  1430.             }
  1431.         }
  1432. #endif /* YYDEBUG */
  1433.         if ( ( ( yy_n += yychar ) < 0 ) || ( yy_n >= YYLAST ) )
  1434.             goto yydefault;
  1435.         if ( yychk[ yy_n = yyact[ yy_n ] ] == yychar )    /*valid shift*/
  1436.         {
  1437.             yychar = -1;
  1438.             yyval = yylval;
  1439.             yy_state = yy_n;
  1440.             if ( yyerrflag > 0 )
  1441.                 yyerrflag--;
  1442.             goto yy_stack;
  1443.         }
  1444.  
  1445.     yydefault:
  1446.         if ( ( yy_n = yydef[ yy_state ] ) == -2 )
  1447.         {
  1448. #if YYDEBUG
  1449.             yytmp = yychar < 0;
  1450. #endif
  1451.             if ( ( yychar < 0 ) && ( ( yychar = yylex() ) < 0 ) )
  1452.                 yychar = 0;        /* reached EOF */
  1453. #if YYDEBUG
  1454.             if ( yydebug && yytmp )
  1455.             {
  1456.                 register int yy_i;
  1457.  
  1458.                 (void)printf( "Received token " );
  1459.                 if ( yychar == 0 )
  1460.                     (void)printf( "end-of-file\n" );
  1461.                 else if ( yychar < 0 )
  1462.                     (void)printf( "-none-\n" );
  1463.                 else
  1464.                 {
  1465.                     for ( yy_i = 0;
  1466.                         yytoks[yy_i].t_val >= 0;
  1467.                         yy_i++ )
  1468.                     {
  1469.                         if ( yytoks[yy_i].t_val
  1470.                             == yychar )
  1471.                         {
  1472.                             break;
  1473.                         }
  1474.                     }
  1475.                     (void)printf( "%s\n", yytoks[yy_i].t_name );
  1476.                 }
  1477.             }
  1478. #endif /* YYDEBUG */
  1479.             /*
  1480.             ** look through exception table
  1481.             */
  1482.             {
  1483.                 register int *yyxi = yyexca;
  1484.  
  1485.                 while ( ( *yyxi != -1 ) ||
  1486.                     ( yyxi[1] != yy_state ) )
  1487.                 {
  1488.                     yyxi += 2;
  1489.                 }
  1490.                 while ( ( *(yyxi += 2) >= 0 ) &&
  1491.                     ( *yyxi != yychar ) )
  1492.                     ;
  1493.                 if ( ( yy_n = yyxi[1] ) < 0 )
  1494.                     YYACCEPT;
  1495.             }
  1496.         }
  1497.  
  1498.         /*
  1499.         ** check for syntax error
  1500.         */
  1501.         if ( yy_n == 0 )    /* have an error */
  1502.         {
  1503.             /* no worry about speed here! */
  1504.             switch ( yyerrflag )
  1505.             {
  1506.             case 0:        /* new error */
  1507.                 yyerror( "syntax error" );
  1508.                 goto skip_init;
  1509.             yyerrlab:
  1510.                 /*
  1511.                 ** get globals into registers.
  1512.                 ** we have a user generated syntax type error
  1513.                 */
  1514.                 yy_pv = yypv;
  1515.                 yy_ps = yyps;
  1516.                 yy_state = yystate;
  1517.                 yynerrs++;
  1518.             skip_init:
  1519.             case 1:
  1520.             case 2:           /* incompletely recovered error */
  1521.                        /* try again... */
  1522.                 yyerrflag = 3;
  1523.                 /*
  1524.                 ** find state where "error" is a legal
  1525.                 ** shift action
  1526.                 */
  1527.                 while ( yy_ps >= yys )
  1528.                 {
  1529.                     yy_n = yypact[ *yy_ps ] + YYERRCODE;
  1530.                     if ( yy_n >= 0 && yy_n < YYLAST &&
  1531.                         yychk[yyact[yy_n]] == YYERRCODE)
  1532.                 {
  1533.                         /*
  1534.                         ** simulate shift of "error"
  1535.                         */
  1536.                         yy_state = yyact[ yy_n ];
  1537.                         goto yy_stack;
  1538.                     }
  1539.                     /*
  1540.                     ** current state has no shift on
  1541.                     ** "error", pop stack
  1542.                     */
  1543. #if YYDEBUG
  1544. #    define _POP_ "Error recovery pops state %d, uncovers state %d\n"
  1545.                     if ( yydebug )
  1546.                         (void)printf( _POP_, *yy_ps,
  1547.                             yy_ps[-1] );
  1548. #    undef _POP_
  1549. #endif
  1550.                     yy_ps--;
  1551.                     yy_pv--;
  1552.                 }
  1553.                 /*
  1554.                 ** there is no state on stack with "error" as
  1555.                 ** a valid shift.  give up.
  1556.                 */
  1557.                 YYABORT;
  1558.             case 3:        /* no shift yet; eat a token */
  1559. #if YYDEBUG
  1560.                 /*
  1561.                 ** if debugging, look up token in list of
  1562.                 ** pairs.  0 and negative shouldn't occur,
  1563.                 ** but since timing doesn't matter when
  1564.                 ** debugging, it doesn't hurt to leave the
  1565.                 ** tests here.
  1566.                 */
  1567.                 if ( yydebug )
  1568.                 {
  1569.                     register int yy_i;
  1570.  
  1571.                     (void)printf( "Error recovery discards " );
  1572.                     if ( yychar == 0 )
  1573.                      (void)printf( "token end-of-file\n" );
  1574.                     else if ( yychar < 0 )
  1575.                        (void)printf( "token -none-\n" );
  1576.                     else
  1577.                     {
  1578.                         for ( yy_i = 0;
  1579.                             yytoks[yy_i].t_val >= 0;
  1580.                             yy_i++ )
  1581.                         {
  1582.                             if ( yytoks[yy_i].t_val
  1583.                                 == yychar )
  1584.                             {
  1585.                                 break;
  1586.                             }
  1587.                         }
  1588.                         (void)printf( "token %s\n",
  1589.                             yytoks[yy_i].t_name );
  1590.                     }
  1591.                 }
  1592. #endif /* YYDEBUG */
  1593.                 if ( yychar == 0 )    /* reached EOF. 
  1594.                                quit */
  1595.                     YYABORT;
  1596.                 yychar = -1;
  1597.                 goto yy_newstate;
  1598.             }
  1599.         }/* end if ( yy_n == 0 ) */
  1600.         /*
  1601.         ** reduction by production yy_n
  1602.         ** put stack tops, etc. so things right after switch
  1603.         */
  1604. #if YYDEBUG
  1605.         /*
  1606.         ** if debugging, print the string that is the user's
  1607.         ** specification of the reduction which is just about
  1608.         ** to be done.
  1609.         */
  1610.         if ( yydebug )
  1611.             (void)printf( "Reduce by (%d) \"%s\"\n",
  1612.                 yy_n, yyreds[ yy_n ] );
  1613. #endif
  1614.         yytmp = yy_n;            /* value to switch 
  1615.                            over */
  1616.         yypvt = yy_pv;            /* $vars top of 
  1617.                            value stack */
  1618.         /*
  1619.         ** Look in goto table for next state
  1620.         ** Sorry about using yy_state here as temporary
  1621.         ** register variable, but why not, if it works...
  1622.         ** If yyr2[ yy_n ] doesn't have the low order bit
  1623.         ** set, then there is no action to be done for
  1624.         ** this reduction.  So, no saving & unsaving of
  1625.         ** registers done.  The only difference between the
  1626.         ** code just after the if and the body of the if is
  1627.         ** the goto yy_stack in the body.  This way the test
  1628.         ** can be made before the choice of what to do is needed.
  1629.         */
  1630.         {
  1631.             /* length of production doubled with extra bit */
  1632.             register int yy_len = yyr2[ yy_n ];
  1633.  
  1634.             if ( !( yy_len & 01 ) )
  1635.             {
  1636.                 yy_len >>= 1;
  1637.                 yyval = ( yy_pv -= yy_len )[1];    
  1638.                   /* $$ = $1 */
  1639.                 yy_state = yypgo[ yy_n = yyr1[ yy_n ] ] +
  1640.                     *( yy_ps -= yy_len ) + 1;
  1641.                 if ( yy_state >= YYLAST ||
  1642.                     yychk[ yy_state =
  1643.                     yyact[ yy_state ] ] != -yy_n )
  1644.                 {
  1645.                     yy_state = yyact[ yypgo[ yy_n ] ];
  1646.                 }
  1647.                 goto yy_stack;
  1648.             }
  1649.             yy_len >>= 1;
  1650.             yyval = ( yy_pv -= yy_len )[1];    /* $$ = $1 */
  1651.             yy_state = yypgo[ yy_n = yyr1[ yy_n ] ] +
  1652.                 *( yy_ps -= yy_len ) + 1;
  1653.             if ( yy_state >= YYLAST ||
  1654.                 yychk[ yy_state = yyact[ yy_state ] ]
  1655.                 != -yy_n )
  1656.             {
  1657.                 yy_state = yyact[ yypgo[ yy_n ] ];
  1658.             }
  1659.         }
  1660.                     /* save until reenter driver code */
  1661.         yystate = yy_state;
  1662.         yyps = yy_ps;
  1663.         yypv = yy_pv;
  1664.     }
  1665.     /*
  1666.     ** code supplied by user is placed in this switch
  1667.     */
  1668.     switch( yytmp )
  1669.     {
  1670.         
  1671. case 1:
  1672. { /* Empty */
  1673.            YYACCEPT
  1674.            } break;
  1675. case 2:
  1676. {
  1677.            ParseResult = yypvt[-1].Nval;
  1678.            YYACCEPT
  1679.            } break;
  1680. case 3:
  1681. { /* Include a file of expressions */
  1682.        /* Read in the file as a giant string, and insert */
  1683.        /* it before the what's left of the current expression. */
  1684.        CHAR *SaveExpression, *NewExpression, c, *s;
  1685.        FILE *expfile;
  1686.        INT i, slen, explen, needed_size;
  1687.  
  1688.        if( !( expfile = VIfopen(id) ) )
  1689.          /* Should use DV standard error reporting using:
  1690.          VEerrsignal( V_SEVERE, V_FILE_OPEN_ERROR, id, "FDSeval" ); */
  1691.          (VOID)S_FPRINTF( stderr, "Couldn't open file: %s\n", id );
  1692.        else
  1693.          {
  1694.          /* Make a copy of what's left of the expression */
  1695.          /* to add it to the end of what we include. */
  1696.          SaveExpression = VIstrclone( (char*)expression );
  1697.  
  1698.          /* Read in the characters from the include file, */
  1699.          /* making sure to grow the string as necessary */
  1700.          i = 0;
  1701.          explen = 512;
  1702.          s = NewExpression = S_ALLOC( explen * (LONG)sizeof(CHAR) );
  1703.          while( EOF != ( c = getc(expfile) ) )
  1704.            {
  1705.            if( i >= explen )
  1706.          { /* We ran out of room */
  1707.          s = S_ALLOC( ( 512 + explen ) * (LONG)sizeof(CHAR) );
  1708.          cpybuf( s, NewExpression, explen );
  1709.          S_FREE( (ADDRESS)NewExpression );
  1710.          NewExpression = s;
  1711.          s = &NewExpression[explen];
  1712.          explen += 512;
  1713.          }
  1714.            *s++ = c;
  1715.            i++;
  1716.            }
  1717.           
  1718.          (VOID)S_FCLOSE( expfile );
  1719.  
  1720.          /* Add a ';' and the current expression to the end */
  1721.          /* making sure there is enough room */
  1722.          slen = S_STRLEN(SaveExpression);
  1723.          needed_size = i + 2 + slen;
  1724.          if( needed_size >= explen )
  1725.          { /* Need more room */
  1726.          s = S_ALLOC( needed_size * (LONG)sizeof(CHAR) );
  1727.          cpybuf( s, NewExpression, i );
  1728.          S_FREE( (ADDRESS)NewExpression );
  1729.          NewExpression = s;
  1730.          s = &NewExpression[i];
  1731.          }
  1732.          *s++ = ';';
  1733.          cpybuf( s, SaveExpression, slen+1 );
  1734.          S_FREE( (ADDRESS)ExpStart );
  1735.          S_FREE( (ADDRESS)SaveExpression );
  1736.          ExpStart = NewExpression;
  1737.          expression = ExpStart;
  1738.          }
  1739.            YYACCEPT
  1740.        } break;
  1741. case 4:
  1742. { /* Error in expression; create a zero generator */
  1743.         ParseResult = PTNcreate( number,(FCN)0,(NODE*)0,
  1744.                    (NODE*)0,(NODE*)0 );
  1745.            YYACCEPT
  1746.            } break;
  1747. case 5:
  1748. { yyval.Sval = ConvertNameToSymbol(id); } break;
  1749. case 6:
  1750. { yyval.ival = CurrentArgIndex; } break;
  1751. case 7:
  1752. { yyval.Nval = PTNcreate( number,(FCN)0,(NODE*)0,(NODE*)0,(NODE*)0 ); } break;
  1753. case 8:
  1754. {
  1755.        /* This is a symbol in the expression that means that */
  1756.        /* we are to get the value from outside the expression */
  1757.        /* parser's environment.  Save the index of the argument */
  1758.        /* so that when we later evaluate the expression, we can */
  1759.        /* bind the index to some value or data source */
  1760.        yyval.Nval = PTNcreate( (DOUBLE)0,(FCN)readvar,
  1761.                (NODE*)0,(NODE*)0,(NODE*)0 );
  1762.  
  1763.        /* Set up the parameter field for readvar */
  1764.        yyval.Nval->params = (ADDRESS)yypvt[-0].ival; /* Save */
  1765.                              /* argument */ 
  1766.                              /* index for later */
  1767.        yyval.Nval->FreeParams = NULL;
  1768.        } break;
  1769. case 9:
  1770. {
  1771.        /* Add symbol to data area */
  1772.        daAddEntry( CurrentParams->data_area, yypvt[-2].Sval );
  1773.        yyval.Nval = PTNcreate( (DOUBLE)0,(FCN)assign,
  1774.                (NODE*)yypvt[-0].Nval,(NODE*)0,(NODE*)0 );
  1775.  
  1776.        /* Set up the parameter field for assign */
  1777.        yyval.Nval->params =
  1778.          (ADDRESS)daGetDatumAddress( CurrentParams->data_area, 
  1779.                     yypvt[-2].Sval );
  1780.        yyval.Nval->FreeParams = NULL;
  1781.        } break;
  1782. case 10:
  1783. { /* Write the expression out to a data source variable */
  1784.        /* if the destination argument is a data source variable */
  1785.        yyval.Nval = PTNcreate( (DOUBLE)0,(FCN)assign_to_dsv,
  1786.                (NODE*)yypvt[-0].Nval,(NODE*)0,(NODE*)0 );
  1787.  
  1788.        /* Set up parameter field for assign_to_dsv */
  1789.        yyval.Nval->params = (ADDRESS)yypvt[-2].ival; /* Save index */
  1790.                              /* of arg to */
  1791.                                                          /* write to. */
  1792.        yyval.Nval->FreeParams = NULL;
  1793.        } break;
  1794. case 11:
  1795. { yyval.Nval = PTNcreate( (DOUBLE)0,cond,yypvt[-4].Nval,
  1796.              yypvt[-2].Nval,yypvt[-0].Nval ); } break;
  1797. case 12:
  1798. {
  1799.        GetFcn(yypvt[-2].Sval, &fcn, &numargs);
  1800.        if( fcn && numargs == 0 )
  1801.          yyval.Nval = PTNcreate( (DOUBLE)0,fcn,(NODE*)0,
  1802.                     (NODE*)0,(NODE*)0 );
  1803.        else
  1804.          {
  1805.          if( fcn == 0 )
  1806.            ErrFcnUndefined( yypvt[-2].Sval );
  1807.          else
  1808.            ErrArgMismatch( yypvt[-2].Sval, numargs, 0 );
  1809.          yyval.Nval = PTNcreate( (DOUBLE)0,(FCN)0,
  1810.                  (NODE*)0,(NODE*)0,(NODE*)0 );
  1811.          }
  1812.        } break;
  1813. case 13:
  1814. {
  1815.        GetFcn(yypvt[-3].Sval, &fcn, &numargs);
  1816.        if( fcn && numargs == 1 )
  1817.          yyval.Nval = PTNcreate( (DOUBLE)0,fcn,
  1818.                     yypvt[-1].Nval,(NODE*)0,(NODE*)0 );
  1819.        else
  1820.          {
  1821.          if( fcn == 0 )
  1822.            ErrFcnUndefined( yypvt[-3].Sval );
  1823.          else
  1824.            ErrArgMismatch( yypvt[-3].Sval, numargs, 1 );
  1825.          yyval.Nval = PTNcreate( (DOUBLE)0,(FCN)0,
  1826.                  (NODE*)0,(NODE*)0,(NODE*)0 );
  1827.          }
  1828.        } break;
  1829. case 14:
  1830. {
  1831.        GetFcn(yypvt[-5].Sval, &fcn, &numargs);
  1832.        if( fcn && numargs == 2 )
  1833.          yyval.Nval = PTNcreate( (DOUBLE)0,fcn,yypvt[-3].Nval,
  1834.                     yypvt[-1].Nval,(NODE*)0 );
  1835.        else
  1836.          {
  1837.          if( fcn == 0 )
  1838.            ErrFcnUndefined( yypvt[-5].Sval );
  1839.          else
  1840.            ErrArgMismatch( yypvt[-5].Sval, numargs, 2 );
  1841.          yyval.Nval = PTNcreate( (DOUBLE)0,(FCN)0,
  1842.                  (NODE*)0,(NODE*)0,(NODE*)0 );
  1843.          }
  1844.        } break;
  1845. case 15:
  1846. {
  1847.        GetFcn(yypvt[-7].Sval, &fcn, &numargs);
  1848.        if( fcn && numargs == 3 )
  1849.          yyval.Nval = PTNcreate( (DOUBLE)0,fcn,yypvt[-5].Nval,
  1850.                     yypvt[-3].Nval,yypvt[-1].Nval );
  1851.        else
  1852.          {
  1853.          if( fcn == 0 )
  1854.            ErrFcnUndefined( yypvt[-7].Sval );
  1855.          else
  1856.            ErrArgMismatch( yypvt[-7].Sval, numargs, 3 );
  1857.          yyval.Nval = PTNcreate( (DOUBLE)0,(FCN)0,
  1858.                  (NODE*)0,(NODE*)0,(NODE*)0 );
  1859.          }
  1860.        } break;
  1861. case 16:
  1862. {
  1863.        /* Add symbol to data area */
  1864.        daAddEntry( CurrentParams->data_area, yypvt[-0].Sval );
  1865.        yyval.Nval = PTNcreate( (DOUBLE)0,(FCN)readsym,
  1866.                (NODE*)0,(NODE*)0,(NODE*)0 );
  1867.  
  1868.        /* Set up the parameter field for readsym */
  1869.        yyval.Nval->params =
  1870.          (ADDRESS)daGetDatumAddress( CurrentParams->data_area, 
  1871.                     yypvt[-0].Sval );
  1872.        yyval.Nval->FreeParams = NULL;
  1873.        } break;
  1874. case 17:
  1875. { yyval.Nval = PTNcreate( (DOUBLE)0,NEtest,yypvt[-2].Nval,
  1876.              yypvt[-0].Nval,(NODE*)0 ); } break;
  1877. case 18:
  1878. { yyval.Nval = PTNcreate( (DOUBLE)0,EQtest,yypvt[-2].Nval,
  1879.              yypvt[-0].Nval,(NODE*)0 ); } break;
  1880. case 19:
  1881. { yyval.Nval = PTNcreate( (DOUBLE)0,GEtest,yypvt[-2].Nval,
  1882.              yypvt[-0].Nval,(NODE*)0 ); } break;
  1883. case 20:
  1884. { yyval.Nval = PTNcreate( (DOUBLE)0,GTtest,yypvt[-2].Nval,
  1885.              yypvt[-0].Nval,(NODE*)0 ); } break;
  1886. case 21:
  1887. { yyval.Nval = PTNcreate( (DOUBLE)0,LEtest,yypvt[-2].Nval,
  1888.              yypvt[-0].Nval,(NODE*)0 ); } break;
  1889. case 22:
  1890. { yyval.Nval = PTNcreate( (DOUBLE)0,LTtest,yypvt[-2].Nval,
  1891.              yypvt[-0].Nval,(NODE*)0 ); } break;
  1892. case 23:
  1893. { yyval.Nval = PTNcreate( (DOUBLE)0,add,yypvt[-2].Nval,
  1894.              yypvt[-0].Nval,(NODE*)0 ); } break;
  1895. case 24:
  1896. { yyval.Nval = PTNcreate( (DOUBLE)0,minus,yypvt[-2].Nval,
  1897.              yypvt[-0].Nval,(NODE*)0 ); } break;
  1898. case 25:
  1899. { yyval.Nval = PTNcreate( (DOUBLE)0,mult,yypvt[-2].Nval,
  1900.              yypvt[-0].Nval,(NODE*)0 ); } break;
  1901. case 26:
  1902. { yyval.Nval = PTNcreate( (DOUBLE)0,divide,yypvt[-2].Nval,
  1903.              yypvt[-0].Nval,(NODE*)0 ); } break;
  1904. case 27:
  1905. { yyval.Nval = PTNcreate( (DOUBLE)0,neg,yypvt[-0].Nval,(NODE*)0,
  1906.              (NODE*)0 ); } break;
  1907. case 28:
  1908. { yyval.Nval = PTNcreate( (DOUBLE)0,pow,yypvt[-2].Nval,
  1909.              yypvt[-0].Nval,(NODE*)0 ); } break;
  1910. case 29:
  1911. { yyval.Nval = PTNcreate( (DOUBLE)0,mod,yypvt[-2].Nval,
  1912.              yypvt[-0].Nval,(NODE*)0 ); } break;
  1913. case 30:
  1914. { yyval.Nval = yypvt[-1].Nval; } break;
  1915.     }
  1916.     goto yystack;        /* reset registers in driver code */
  1917. }
  1918.